#include "cg_local.h"
#include <math.h>


//================================//
//		NDA code for cgame		  //
//================================//
// Variables used for drawing arrows on hud:
enum {NONE,RESET,DRAW_UP,DRAW_DOWN,DRAW_LEFT,DRAW_RIGHT};
static int arrowCount=0;
static int arrows[6];
static qboolean firstTime = qtrue;
static qboolean firstTimeCast = qtrue;
static int oldUserCmd = 0;
// Variables used for drawing buff state on hud:
static qboolean buffActive = qfalse;

/*
==============
CG_PlayElements

Draws the casting/spell actions
==============
*/
//--------------------------------------------------------------
void CG_PlayElements( centity_t *cent ) {
//--------------------------------------------------------------

	//CG_Printf("%f, %f, %f\n", cent->lerpAngles[0], cent->lerpAngles[1], cent->lerpAngles[2]);
	//CG_Printf("%f, %f, %f\n", cent->lerpOrigin[0], cent->lerpOrigin[1], cent->lerpOrigin[2]); 
	CG_DrawSlotIcons();

	/*if (s->ndaElement!=-1)
	{// Something was casted:
		switch ( s->ndaElement )
		{
		case ELEMENT_ATTACK_BEAM:
			{
				vec3_t	start, fwd, axis[3];
				
				if ( s->ndaFlags == ATTACK_BEAM_START ) 
				{
					cent->elementInfo.soundPlayed = qfalse; 
				}

				VectorCopy (cent->lerpOrigin, start);
				start[2] += DEFAULT_VIEWHEIGHT;

				AngleVectors (cent->lerpAngles, fwd, NULL, NULL);
				AnglesToAxis (cent->lerpAngles, axis);

				//VectorMA (vectorStart, Distance, VectorEnd, Result)
				VectorMA (start, 30, fwd, start);

				trap_FX_PlayEntityEffectID (cgs.effects.ndaAttackBeamBall, start, axis, -1, -1, -1, -1);
				trap_FX_PlayEntityEffectID (cgs.effects.ndaAttackBeamRing, start, axis, -1, -1, -1, -1);

				if ( s->ndaFlags == ATTACK_BEAM_CHARGED ) {
					trap_FX_PlayEntityEffectID (cgs.effects.ndaAttackBeamBeam, start, axis, -1, -1, -1, -1);
				}
			}
			break;

		case ELEMENT_SHIELD:
			{
				/*vec3_t	start, fwd, axis[3], angles, dir;
				VectorCopy (cent->lerpOrigin, start);
				
				if ( s->ndaFlags == SHIELD_START )
				{
					efxStarted=qfalse;
				}

				if (efxStarted==qfalse) {
					efxStarted = qtrue;
					oldEfxStarted = start[2] - 65;
				}

				if ( (efxStarted == qtrue) && (oldEfxStarted < start[2]) ) {
					oldEfxStarted += 1;
					start[2]=oldEfxStarted;
				}

				AngleVectors (cent->lerpAngles, fwd, NULL, NULL);
				AnglesToAxis (cent->lerpAngles, axis);
				
				VectorCopy (cent->lerpAngles, angles);
				angles[ROLL] = 0;angles[PITCH] = 0;
				AngleVectors (angles, NULL, NULL, dir);

				trap_FX_PlayEffectID (cgs.effects.ndaShieldCylinder, start, dir, -1, -1);
				trap_FX_PlayEffectID (cgs.effects.ndaShieldCylinder2, start, dir, -1, -1);
				trap_FX_PlayEffectID (cgs.effects.ndaShieldLeaves, cent->lerpOrigin, dir, -1, -1);
			}
			break;

		case ELEMENT_HEAL:
			{
				/*vec3_t	start, fwd, axis[3], angles, dir;
				VectorCopy (cent->lerpOrigin, start);

				if ( s->ndaFlags == HEAL_START )
				{
					efxStarted=qfalse;
				}

				if (efxStarted==qfalse) {
					efxStarted = qtrue;
					start[2] -= 100;
					oldEfxStarted = start[2];
				}
				if ( (efxStarted == qtrue) && (oldEfxStarted < start[2]) ) {
					oldEfxStarted += 1;
					start[2]=oldEfxStarted;
				}

				AngleVectors (cent->lerpAngles, fwd, NULL, NULL);
				AnglesToAxis (cent->lerpAngles, axis);
				
				VectorCopy (cent->lerpAngles, angles);
				angles[ROLL] = 0;angles[PITCH] = 0;
				AngleVectors (angles, NULL, NULL, dir);

				trap_FX_PlayEffectID (cgs.effects.ndaHealBlood, start, dir, -1, -1);
				trap_FX_PlayEffectID (cgs.effects.ndaHealBlood2, start, dir, -1, -1);
			}
			break;

		default: 
			break;
		}
	}*/
}

void resetCastSound(){
	if (firstTimeCast!=qtrue)
	firstTimeCast=qtrue;
}
/*
==============
CG_DrawSpellBuffs

Draws the current arrow combination over the slots
==============
*/
void CG_DrawSpellBuffs ()
{
	if (pm->ps->ndaBuffFlags == 1)
		buffActive = qtrue;
	else
		buffActive = qfalse; 

	if (buffActive == qtrue)
	{
		int icon_size = 20;
		int pad = 3;
		int i;
		int x = (SCREEN_WIDTH/5)-(icon_size-2); 
		int y = SCREEN_HEIGHT-(icon_size);

		int endx = icon_size;
		int endy = icon_size;

		if (cg.snap->ps.zoomMode)
		{ //don't display over zoom mask
			return;
		}

		if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_SPECTATOR)
		{ 
			return; 
		}

		CG_DrawPic( x, y, endx, endy, cgs.media.ndaIconShieldBuff);
	}
}

/*
==============
CG_DrawArrowIcons

Draws the current arrow combination over the slots
==============
*/
static void CG_DrawArrowIcons ()
{
	int icon_size = 40;
	int pad = 12;
	int i;
	int x = (SCREEN_WIDTH/2)-(icon_size+(pad/2)+(icon_size+pad)*2);
	int y = SCREEN_HEIGHT - icon_size*2;

	int endx = icon_size;
	int endy = icon_size;

	for (i=0;i<arrowCount;i++)
	{
		switch(arrows[i])
		{
			case DRAW_UP:
				CG_DrawPic( x, y, endx, endy, cgs.media.ndaArrowUp);
				x += (icon_size+pad);
				break;
			case DRAW_DOWN:
				CG_DrawPic( x, y, endx, endy, cgs.media.ndaArrowDown);
				x += (icon_size+pad);
				break;
			case DRAW_LEFT:
				CG_DrawPic( x, y, endx, endy, cgs.media.ndaArrowLeft);
				x += (icon_size+pad);
				break;
			case DRAW_RIGHT:
				CG_DrawPic( x, y, endx, endy, cgs.media.ndaArrowRight);
				x += (icon_size+pad);
				break;
			default:
				break;
		}
	}
}

void CG_ResetArrowCount( void ){
	arrowCount=0;
}

/*
==============
CG_DrawArrows

Draws the arrows pressed by the player.
==============
*/
//--------------------------------------------------------------
void CG_DrawArrows(int arrow)					
//--------------------------------------------------------------
{
	if (arrow == RESET && arrowCount != 0 || pm->ps->ndaFlags == SPELL_END  ) 
		CG_ResetArrowCount();
	else if ( arrowCount < 6 && arrow != -1 ) 
	{
		if ( pm->ps->ndaComboFlags == NONE ) //both=0 means you're ONLY pressing cast button
		{//This make possible consecutive combinations of the same key:
			firstTime = qtrue;
		}
		if ( (pm->ps->ndaComboFlags == DRAW_UP && oldUserCmd != DRAW_UP) 
			|| (pm->ps->ndaComboFlags == DRAW_UP && firstTime == qtrue) ){
			arrows[arrowCount] = arrow;
			firstTime = qfalse;
			oldUserCmd=DRAW_UP;
			arrowCount++;
		}
		if ( (pm->ps->ndaComboFlags == DRAW_DOWN && oldUserCmd != DRAW_DOWN) 
			|| (pm->ps->ndaComboFlags == DRAW_DOWN && firstTime == qtrue) ){
			arrows[arrowCount] = arrow;
			firstTime = qfalse;
			oldUserCmd=DRAW_DOWN;
			arrowCount++;
		}
		if ( (pm->ps->ndaComboFlags == DRAW_LEFT && oldUserCmd != DRAW_LEFT) 
			|| (pm->ps->ndaComboFlags == DRAW_LEFT && firstTime == qtrue) ){
			arrows[arrowCount] = arrow;
			firstTime = qfalse;
			oldUserCmd=DRAW_LEFT;
			arrowCount++;
		}
		if ( (pm->ps->ndaComboFlags == DRAW_RIGHT && oldUserCmd != DRAW_RIGHT) 
			|| (pm->ps->ndaComboFlags == DRAW_RIGHT && firstTime == qtrue) ){
			arrows[arrowCount] = arrow;
			firstTime = qfalse;
			oldUserCmd=DRAW_RIGHT;
			arrowCount++;
		}
	}
	CG_DrawArrowIcons();
}

/*
==============
CG_DrawSpellIcons

Draws the spell icons
==============
*/
//--------------------------------------------------------------
void CG_DrawSpellIcons(void)		
//--------------------------------------------------------------
{
	int icon_size = 30;
	int pad = 3;
	int i;
	int x = icon_size/2;
	int y = icon_size/2;

	int endx = icon_size;
	int endy = icon_size;

	if (cg.snap->ps.zoomMode)
	{ //don't display over zoom mask
		return;
	}

	if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_SPECTATOR)
	{ 
		return; 
	}

	CG_DrawPic( x, y, endx, endy, cgs.media.ndaIconAttackBeam);
	y += (icon_size+pad);
	CG_DrawPic( x, y, endx, endy, cgs.media.ndaIconShield);
	y += (icon_size+pad);
	CG_DrawPic( x, y, endx, endy, cgs.media.ndaIconHeal);
	y += (icon_size+pad);
}

/*
==============
CG_DrawSpellCombinations

Draws the spell icons
==============
*/
//--------------------------------------------------------------
void CG_DrawSpellCombinations(void)		
//--------------------------------------------------------------
{
	int icon_size = 30;
	int pad = 3;
	int i;
	int x = icon_size+20;
	int y = icon_size/2;

	int endx = icon_size*8;
	int endy = icon_size;

	if (cg.snap->ps.zoomMode)
	{ //don't display over zoom mask
		return;
	}

	if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_SPECTATOR)
	{ 
		return; 
	}

	CG_DrawPic( x, y, endx, endy, cgs.media.ndaAtkBeamComb);
	y += (icon_size+pad);
	CG_DrawPic( x, y, endx, endy, cgs.media.ndaShieldComb);
	y += (icon_size+pad);
	CG_DrawPic( x, y, endx, endy, cgs.media.ndaHealComb);
	y += (icon_size+pad);
}
/*
==============
CG_DrawSlotIcons

Draws the slots for the casting combination
==============
*/
//--------------------------------------------------------------
void CG_DrawSlotIcons(void)		
//--------------------------------------------------------------
{
	int icon_size = 40;
	int pad = 12;
	int i;
	int x = (SCREEN_WIDTH/2)-(icon_size+(pad/2)+(icon_size+pad)*2);
	int y = SCREEN_HEIGHT - icon_size*2;

	int endx = icon_size;
	int endy = icon_size;
	
	CG_DrawSpellCombinations();  
	
	if (cg.snap->ps.zoomMode)
	{ //don't display over zoom mask
		return;
	}

	if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_SPECTATOR)
	{ 
		return; 
	}

	for (i=0; i<6; i++)
	{
		CG_DrawPic( x, y, endx, endy, cgs.media.ndaSlotIcon);
		x += (icon_size+pad);
	}
}

// ================================== Code to change +button12 to +cast: ONLY works for Windows =====================================//
#define SYNC_BUTTON(a, b, c, d) Cmd_RemoveCommand(a); Cmd_RemoveCommand(b); Cmd_AddCommand( a, FindCommandPointer(c) ); Cmd_AddCommand( b, FindCommandPointer(d) );

void *Cmd_AddCommand( const char *name, void *funcptr )
{
	__asm
	{
		mov eax, name
		mov ebx, funcptr
		mov edx, 0x436DA0
		call edx
	}
}

void *Cmd_RemoveCommand( const char *name )
{
	__asm
	{
		mov edx, name
		mov eax, 0x436E30
		call eax
	}
}

// Command lookup
typedef struct jacmd_s
{
	struct jacmd_s *next;
	const char* name;
	void *function;
} jacmd_t;

void *FindCommandPointer( const char *command )
{//Raz - Usage: FindCommandPointer("+buttonX")
	jacmd_t *cmd;
	
	for (cmd = *(jacmd_t **)0xB3CC18; cmd; cmd = cmd->next)
	{
		if ( !Q_stricmp( command, cmd->name ) )
		{
			return cmd->function;
		}
	}
	return NULL;
}

void AM_SyncButtons( void )
{
	SYNC_BUTTON( "+cast",			"-cast",			"+button12",		"-button12" );
}